/*
method
go中虽然没有class，但依旧有method
通过显示说明receiver来实现与某个类型的组合
只能为同一个包中的类型定义方法
receiver可以是类型的值或者指针
不存在方法重载
可以使用值或指针来调用方法，编译器会自动完成转换
从某种意义上来说，方法是函数的语法糖，因为receiver其实就是方法
	所接收的第一个参数（method value vs method expression）
如果外部结构和嵌入结构存在同名方法，则优先调用外部结构的方法
类型别名不会拥有底层类型所附带的方法
方法可以调用结构中的非公开字段
*/
package main

import (
	"fmt"
)

type A struct {
	Name string
}

func (a A) PrintValue() {
	a.Name = "AA"
	fmt.Println("in func (a A) PrintValue")
}
func (a *A) PrintPointer() {
	a.Name = "AA"
	fmt.Println("in func (a *A) PrintPointer")
}

type TZ int

func (a *TZ) Print() {
	fmt.Println("TZ")
}

type B struct {
	Name          string
	lowercaseAttr int //小写成员的可见性是其struct所在包及其函数中，函数的可见性规则同成员
}

func (b *B) Print() {
	fmt.Println("start in func (b *B) Print()")
	b.lowercaseAttr = 123
	fmt.Println("B.lowercaseAttr = 123")
	fmt.Println("end in func (b *B) Print()")
}

func (a *TZ) Increase(num int) {
	*a += TZ(num) //int的类型别名TZ和int不能混合运算，需要先将int转为TZ类型  TZ(num)
	fmt.Println("TZ")
}

func main() {
	a := A{Name: "A"}
	a.PrintValue()    //method value
	(A).PrintValue(a) //method expression
	fmt.Println(a)

	a.PrintPointer()      //method value
	(*A).PrintPointer(&a) //method expression
	fmt.Println(a)
	fmt.Println("--------------type alias add method to type int-----------------")
	var b TZ
	b.Print()       //method value     给基础类型间接加了Print方法
	(*TZ).Print(&b) //method expression
	fmt.Println("--------------type lowercase field-----------------")
	c := B{}
	fmt.Println("B.lowercaseAttr =", c.lowercaseAttr)
	c.Print()
	fmt.Println("B.lowercaseAttr =", c.lowercaseAttr)
	fmt.Println("--------------classroom work-----------------")
	var d TZ
	d.Increase(100)

}
